package edu.maping.easy.composer;

import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.ArrayList;

import controlP5.ControlP5;

import processing.core.PApplet;
import processing.core.PFont;
import processing.xml.XMLElement;
import edu.maping.easy.ControlFacade;
import edu.maping.easy.gui.Button;
import edu.maping.easy.gui.GUIEvent;
import edu.maping.easy.gui.GuiFactory;
import edu.maping.easy.gui.Slider;
import edu.maping.easy.io.KeyBoardInteraction;
import edu.maping.easy.model.GUIInteraction;
import edu.maping.easy.model.EasyMappingPlugin;
import edu.maping.easy.model.MouseInteraction;
import edu.maping.easy.model.Thing;
import edu.maping.easy.model.World;
import edu.maping.easy.sequence.ActionEventList;
import edu.maping.easy.sequence.ArrayListStepper;
import edu.maping.easy.sequence.Sequencer;
import edu.maping.easy.sequence.SequenceStep;

public class Composer implements EasyMappingPlugin, GUIInteraction,
		MouseInteraction {

	private boolean doing = false;
	public Sequencer sequencer = null;
	private ArrayListStepper<ComposeUnit> units = new ArrayListStepper<ComposeUnit>();
	private ComposeUnit composeUnit = null;
	private Button bang = null;
	private Slider sliderStart = null;
	private Slider sliderEnd = null;
	PFont pFont = null;

	private Button left;
	private Button rigth;

	private boolean started = false;
	private long startedMoment = 0;

	String lastName = null;

	@Override
	public void draw(PApplet pApplet) {

		if (doing) {

			renderEditor(pApplet);
		}

		long velocity = 20;

		if (started && startedMoment > 0) {
			step(pApplet, velocity);
		}

	}

	private void step(PApplet pApplet, long velocity) {

		long now = pApplet.frameCount - startedMoment;
		now /= velocity;

		for (int index = 0; index < units.seqs.size(); index++) {
			ComposeUnit unit = units.seqs.get(index);
			if (unit.start < now && now < unit.end) {

				if (lastName == null) {
					System.out.println("Se inicio la sequencia "
							+ unit.sequence.name);
				} else if (!lastName.equals(unit.sequence.name)) {
					lastName = unit.sequence.name;
					System.out.println("Se inicio la sequencia "
							+ unit.sequence.name);
				}

				if (pApplet.frameCount % 60 == 0) {
					sequencer.nextStep(false);
				}

				sequencer.setActionSequence(unit.sequence);
				sequencer.draw(pApplet, true);
			}
		}
	}

	private void renderEditor(PApplet pApplet) {
		int x = 20;
		int y = pApplet.height - 75;

		for (int index = 0; index < units.seqs.size(); index++) {
			ComposeUnit unit = units.seqs.get(index);

			pApplet.text(unit.sequence.name, x + index * 25, y);

			if (index == units.getCurrent()) {
				pApplet.noFill();
				pApplet.rect((25 * index) + x + 10, y - 15, (25 * index) + x
						- 5, y + 15);
			}
		}
	}

	@Override
	public String getName() {
		return null;
	}

	@Override
	public void setParameters(Thing thing) {

	}

	@Override
	public void setup(PApplet pApplet) {

	}

	@Override
	public void setup(PApplet pApplet, GuiFactory guiFactory) {

		pFont = pApplet.loadFont("Ziggurat-HTF-Black-32.vlw");
		pApplet.textFont(pFont, 14);

		edu.maping.easy.gui.Button startCompose = guiFactory.newButton(
				"Composer", 330, 10, 75, 20);

		bang = guiFactory.newButton("Add", pApplet.width - 50,
				pApplet.height - 50, 20, 20);
		bang.setDrawable(false);

		sliderStart = guiFactory.newSlider("Start", pApplet.width - 250, 20, 1,
				1000, 1);
		sliderStart.setWidth(pApplet.width - 250);
		sliderStart.setDrawable(false);
		sliderStart
				.setPosition(sliderStart.getWidth() / 2, pApplet.height - 50);

		sliderEnd = guiFactory.newSlider("End", pApplet.width - 250, 20, 1,
				1000, 1);
		sliderEnd.setWidth(pApplet.width - 250);
		sliderEnd.setDrawable(false);
		sliderEnd.setPosition(sliderEnd.getWidth() / 2, pApplet.height - 25);

		left = guiFactory.newButton("<--", pApplet.width - 150,
				pApplet.height - 25, 30, 20);
		left.setDrawable(false);
		rigth = guiFactory.newButton("-->", pApplet.width - 120,
				pApplet.height - 25, 30, 20);
		rigth.setDrawable(false);
	}

	@Override
	public void start(World world, PApplet pApplet, ControlP5 controlP5) {
		started = true;
		startedMoment = pApplet.frameCount;
	}

	@Override
	public void stop(World world, PApplet pApplet, ControlP5 controlP5) {
		started = false;
		startedMoment = 0;
	}

	@Override
	public void controlEvent(GUIEvent theEvent) {

		if (theEvent.name().equals("Composer")) {
			doing = !doing;
			if (doing) {
				sequencer.showSequenceList();
				bang.setDrawable(true);
				sliderStart.setDrawable(true);
				sliderEnd.setDrawable(true);
				left.setDrawable(true);
				rigth.setDrawable(true);
			} else {
				sequencer.hideSequenceList();
				bang.setDrawable(false);
				sliderStart.setDrawable(false);
				sliderEnd.setDrawable(false);
				left.setDrawable(false);
				rigth.setDrawable(false);
			}
		}

		if (doing && theEvent.name().equals("Add")) {
			composeUnit = new ComposeUnit();
			ArrayListStepper<SequenceStep> actionSequence = sequencer
					.getActionSequence();
			composeUnit.sequence = actionSequence;
			units.seqs.add(composeUnit);
			units.next();
		}

		// if (theEvent.isController()) {
		if (theEvent.controller() == sliderStart) {
			if (composeUnit != null) {
				composeUnit.start = sliderStart.value;
			}
		}
		//
		if (theEvent.controller() == sliderEnd) {
			if (composeUnit != null) {
				composeUnit.end = sliderEnd.value;
			}
		}
		//
		if (theEvent.controller().equals(left)) {
			units.previous();
			updateComposeUnitInfoo();
		}

		if (theEvent.controller().equals(rigth)) {
			units.next();
			updateComposeUnitInfoo();
		}
		// }

	}

	@Override
	public void KeyPressed(KeyBoardInteraction key) {
		// TODO Auto-generated method stub

	}

	@Override
	public void editKeyPressed(int key, Thing thing) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean mouseClicked(int mouseX, int mouseY, Thing newThing,
			MouseEvent mouseEvent) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void mouseDragged(int mouseX, int mouseY, Thing newThing) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePreassed(int mouseX, int mouseY, Thing newThing) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(int mouseX, int mouseY, Thing newThing) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		if (!doing)
			return;

		int rotation = e.getWheelRotation();
		if (rotation > 0) {
			units.previous();
		} else if (rotation < 0) {
			units.next();
		}
		updateComposeUnitInfoo();
	}

	private void updateComposeUnitInfoo() {
		try {
			composeUnit = units.getCurrentElement();
			sliderStart.setValue(composeUnit.start);
			sliderEnd.setValue(composeUnit.end);
			sequencer.setActionSequence(composeUnit.sequence);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void mouseMoved(int mouseX, int mouseY) {
		// TODO Auto-generated method stub
	}

	public XMLElement xmlIzation() {
		XMLElement seqsElement = new XMLElement();
		seqsElement.setName("Composer");

		for (ComposeUnit unit : units.seqs) {
			XMLElement element = unit.xmlIzation();
			seqsElement.addChild(element);
		}
		return seqsElement;
	}

	public void desXmlIzation(XMLElement seqsElement) {

		if (!seqsElement.getName().equals("Composer"))
			return;

		for (XMLElement componseUnitXML : seqsElement.getChildren()) {
			ComposeUnit composeUnit = new ComposeUnit();
			composeUnit.desXmlIzation(componseUnitXML, sequencer);
			units.seqs.add(composeUnit);
		}
	}
}
